/** 
  Copyright (c) 2008, 2009 Claudio Imbrenda
  This program is released under the terms of the
  GNU GPL version 3 or later.
*/

package interfaccia;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.BorderLayout;
import javax.swing.*;
import java.util.*;
import macchina.*;

/**
 * @author Claudio Imbrenda
 */
public class MRTapeReaderPanel extends JPanel implements AdattatoreEntrata {
      
  private static ResourceBundle bundle_interfaccia = 
          ResourceBundle.getBundle("interfaccia/Bundle_interfaccia");  
  
       
    private List<Byte> nastro = new ArrayList<Byte>();
    
    private List<MRTapeElementPanel> elems=new LinkedList<MRTapeElementPanel>();
    
    private int current=0;
    private boolean isloop;

    Macchina m;

    public MRTapeReaderPanel(){
        this(null);
    }
    
    /** Creates new form MRTapeReaderPanel */
    public MRTapeReaderPanel(Macchina mm) {
        initComponents();

        btnAddFirst.setVisible(false);
        btnAddLast.setVisible(false);
        jSeparator1.setVisible(false);

        m=mm;

        /*
        last = new MRTapeElementPanel();
        last.setEditable(false);
        last.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if(e.getActionCommand().equals("add"))
                    addelem((byte)0, -1);
                else if(e.getActionCommand().equals("curr")){
                    if(current<elems.size())
                        elems.get(current).setSelected(false);
                    current=nastro.size();
                    remake_hist();
                }else if(e.getActionCommand().equals("entered")){
                    for(MRTapeElementPanel ee:elems)
                        ee.do_mouseExited();
                    erst.do_mouseExited();
                }
            }
        });
        jPanel4.add(last);
        erst = new MRTapeElementPanel();
        erst.setEditable(false);
        erst.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if(e.getActionCommand().equals("add"))
                    addelem((byte)0, 0);
                else if(e.getActionCommand().equals("curr")){
                    if(current<elems.size())
                        elems.get(current).setSelected(false);
                    current=0;
                    if(current<elems.size())
                        elems.get(current).setSelected(true);
                    remake_hist();
                }else if(e.getActionCommand().equals("entered")){
                    for(MRTapeElementPanel ee:elems)
                        ee.do_mouseExited();
                    last.do_mouseExited();
                }
            }
        });
        jPanel4.add(erst, 0);
        */
        JLabel l=new JLabel("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
        JPanel p=new JPanel(new BorderLayout());
        p.add(l, BorderLayout.NORTH);

        jPanel4.add(p, 0);
        l.setHorizontalAlignment(JLabel.LEFT);

        l=new JLabel("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");
        p=new JPanel(new BorderLayout());
        p.add(l, BorderLayout.SOUTH);
        jPanel4.add(p);
        l.setHorizontalAlignment(JLabel.LEFT);
    }

    private void remake_hist(){
        histcont.removeAll();
        for(int cx=current;cx<nastro.size();cx++){
            histcont.add(new MRTapeElementPanel(true, nastro.get(cx)));
        }
        histcnt2.validate();
        historicalview2.validate();
    }

    private void _edit(MRTapeElementPanel e){
        int idx = elems.indexOf(e);
        nastro.set(idx, e.getValue());

        try{
        if(idx>=current)
            ((MRTapeElementPanel)histcont.getComponent(idx-current))
                    .setValue(e.getValue());
        }catch(ClassCastException ignore){}
    }

    private void _del(MRTapeElementPanel e){
        int idx = elems.indexOf(e);
        if(idx<current)current--;
        if((idx==current)&&(current<elems.size()))
            elems.get(current).setSelected(true);
        elemsPanel.remove(e);
        elems.remove(idx);
        nastro.remove(idx);
        jScrollPane1.validate();
        jScrollPane1.repaint();
        if(idx>=current)remake_hist();
    }

    private void addelem(byte v){
        addelem(v, -1);
    }


    private void addelem(byte v, int idx){
        final MRTapeElementPanel neu = new MRTapeElementPanel();
        if(idx>=elems.size())idx=-1;

        neu.setValue(v);
        neu.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                
                if(e.getActionCommand().equals("edit"))
                    _edit(neu);
                else if(e.getActionCommand().equals("del"))
                    _del(neu);
                else if(e.getActionCommand().equals("add")){
                    int ix=0;
                    ix=elems.indexOf(neu)+1;
                    addelem((byte)0, ix);
                }else if(e.getActionCommand().equals("curr")){
                    int ix=0;
                    ix=elems.indexOf(neu);
                    if(current<elems.size())
                        elems.get(current).setSelected(false);
                    current=ix;
                    if(current<elems.size())
                        elems.get(current).setSelected(true);
                    remake_hist();
                }else if(e.getActionCommand().equals("entered")){
                    for(MRTapeElementPanel ee:elems)
                        if(ee!=neu)ee.do_mouseExited();
                }else {
                    // ?
                }
            }
        });
        
        if(idx==-1)elemsPanel.add(neu);
        else elemsPanel.add(neu, idx);

        if(idx!=-1)nastro.add(idx,v);
        else nastro.add(v);

        if(elems.size()==0){
            current=0;
            neu.setSelected(true);
            elems.add(neu);
            histcont.add(new MRTapeElementPanel(true, v));
            histcnt2.validate();
            historicalview2.validate();
        }else if(idx!=-1){
            elems.add(idx,neu);
            if(idx<=current)current++;
            if(idx>=current)remake_hist();
        }else{
            elems.add(neu);
            histcont.add(new MRTapeElementPanel(true, v));
            histcnt2.validate();
            historicalview2.validate();
        }
        if(jCheckBox6.isSelected())neu.setEditable(true);

        
        elemsPanel.validate();
        jScrollPane1.validate();   
    }


//    private static final String ilt="<html><body><table><tr><td>"+
//          bundle_interfaccia.getString("base_10:")+"</td><td>$base10</td></tr><tr><td>"+
//          bundle_interfaccia.getString("base_16:")+"</td><td>$base16</td></tr><tr><td>"+
//          bundle_interfaccia.getString("base_2:")+"</td><td><font size=\"-3\">$base2</font></td></tr><tr><td>"+
//          bundle_interfaccia.getString("carattere:")+"</td><td>$char</td></tr><tr><td>"+
//          "</table></body></html>";
//    private static String _mktext(byte v){
//        return ilt.replace("$base10", ""+v)
//                         .replace("$base16", niceformat(v, null, 4))
//                         .replace("$base2", niceformat(v, null, 2))
//                         .replace("$char",niceformat(v,null,5));
//    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {

    historicalview = new javax.swing.JPanel();
    historicalview2 = new javax.swing.JScrollPane();
    histcnt2 = new javax.swing.JPanel();
    histcont = new javax.swing.JPanel();
    jLabel1 = new javax.swing.JLabel();
    jPanel3 = new javax.swing.JPanel();
    jPanel1 = new javax.swing.JPanel();
    btnRemove = new javax.swing.JButton();
    jCheckBox6 = new javax.swing.JCheckBox();
    jCheckBox1 = new javax.swing.JCheckBox();
    jSeparator2 = new javax.swing.JSeparator();
    btnAddFirst = new javax.swing.JButton();
    btnAddLast = new javax.swing.JButton();
    jSeparator1 = new javax.swing.JSeparator();
    jPanel5 = new javax.swing.JPanel();
    jScrollPane1 = new javax.swing.JScrollPane();
    jPanel2 = new javax.swing.JPanel();
    jPanel4 = new javax.swing.JPanel();
    elemsPanel = new javax.swing.JPanel();

    historicalview.setLayout(new java.awt.BorderLayout());

    historicalview2.setBorder(null);
    historicalview2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    historicalview2.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

    histcnt2.setLayout(new java.awt.BorderLayout());

    histcont.setLayout(new javax.swing.BoxLayout(histcont, javax.swing.BoxLayout.Y_AXIS));
    histcnt2.add(histcont, java.awt.BorderLayout.PAGE_START);

    historicalview2.setViewportView(histcnt2);

    historicalview.add(historicalview2, java.awt.BorderLayout.CENTER);

    jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
    jLabel1.setText("↑↑↑↑↑↑↑");
    historicalview.add(jLabel1, java.awt.BorderLayout.NORTH);

    setLayout(new java.awt.BorderLayout());

    jPanel3.setLayout(new java.awt.BorderLayout());

    jPanel1.setBorder(javax.swing.BorderFactory.createEmptyBorder(5, 5, 5, 5));
    jPanel1.setLayout(new java.awt.GridLayout(0, 1, 0, 6));

    btnRemove.setText(bundle_interfaccia.getString("Rimuovi_nastro")); // NOI18N
    btnRemove.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        btnRemoveActionPerformed(evt);
      }
    });
    jPanel1.add(btnRemove);

    java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("interfaccia/Bundle_interfaccia"); // NOI18N
    jCheckBox6.setText(bundle.getString("Modifica_nastro")); // NOI18N
    jCheckBox6.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        jCheckBox6ActionPerformed(evt);
      }
    });
    jPanel1.add(jCheckBox6);

    jCheckBox1.setText(bundle.getString("Tape_loop")); // NOI18N
    jCheckBox1.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        jCheckBox1ActionPerformed(evt);
      }
    });
    jPanel1.add(jCheckBox1);
    jPanel1.add(jSeparator2);

    btnAddFirst.setText(bundle.getString("Aggiungi_in_cima")); // NOI18N
    btnAddFirst.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        btnAddFirstActionPerformed(evt);
      }
    });
    jPanel1.add(btnAddFirst);

    btnAddLast.setText(bundle.getString("Aggiungi_in_fondo")); // NOI18N
    btnAddLast.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        btnAddLastActionPerformed(evt);
      }
    });
    jPanel1.add(btnAddLast);
    jPanel1.add(jSeparator1);

    jPanel3.add(jPanel1, java.awt.BorderLayout.NORTH);

    add(jPanel3, java.awt.BorderLayout.EAST);

    jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    jScrollPane1.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

    jPanel2.setLayout(new javax.swing.BoxLayout(jPanel2, javax.swing.BoxLayout.X_AXIS));

    jPanel4.setLayout(new javax.swing.BoxLayout(jPanel4, javax.swing.BoxLayout.Y_AXIS));

    elemsPanel.setLayout(new javax.swing.BoxLayout(elemsPanel, javax.swing.BoxLayout.Y_AXIS));
    jPanel4.add(elemsPanel);

    jPanel2.add(jPanel4);

    jScrollPane1.setViewportView(jPanel2);

    javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5);
    jPanel5.setLayout(jPanel5Layout);
    jPanel5Layout.setHorizontalGroup(
      jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(jPanel5Layout.createSequentialGroup()
        .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 456, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addContainerGap(143, Short.MAX_VALUE))
    );
    jPanel5Layout.setVerticalGroup(
      jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 439, Short.MAX_VALUE)
    );

    add(jPanel5, java.awt.BorderLayout.CENTER);
  }// </editor-fold>//GEN-END:initComponents

    private void btnRemoveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRemoveActionPerformed
        nastro.clear();
        elems.clear();
        elemsPanel.removeAll();
        elemsPanel.validate();
        histcont.removeAll();
        histcont.validate();
        jScrollPane1.validate();
        jScrollPane1.repaint();
}//GEN-LAST:event_btnRemoveActionPerformed

    private void jCheckBox6ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBox6ActionPerformed
        boolean v = jCheckBox6.isSelected();
        for(MRTapeElementPanel c:elems)
            if(c!=null)
                c.setEditable(v);
        
        btnAddFirst.setVisible(v);
        btnAddLast.setVisible(v);
        jSeparator1.setVisible(v);

    }//GEN-LAST:event_jCheckBox6ActionPerformed

    private void jCheckBox1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBox1ActionPerformed
        setLoop(true);
    }//GEN-LAST:event_jCheckBox1ActionPerformed

    private void btnAddLastActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAddLastActionPerformed
        addelem((byte)0, -1);
}//GEN-LAST:event_btnAddLastActionPerformed

    private void btnAddFirstActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAddFirstActionPerformed
        addelem((byte)0, 0);
    }//GEN-LAST:event_btnAddFirstActionPerformed

    public byte read() {
        byte res;
        boolean running = false;

        if(m!=null)running=m.isRunning();

        if(current<nastro.size()){
            /*if(!running)*/elems.get(current).setSelected(false);

            res = nastro.get(current++);
            if(isloop)current %= nastro.size();

            if(/*(!running) && */current<nastro.size()){
                MRTapeElementPanel c = elems.get(current);
                c.setSelected(true);
                jPanel2.scrollRectToVisible(c.getBounds());
                  SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                      if(histcont.getComponentCount()>0){
                      histcont.remove(0);
                      histcont.validate();
                      historicalview.validate();     
                      }
                    }
                  });
//                  System.err.println("rimuovo, perche` = "+histcont.getComponentCount());

            }else {
              remake_hist();          
            }
            
        }else{
            res=0;
            //if(!running)jPanel2.scrollRectToVisible(last.getBounds());
        }
        validate();
        histcont.validate();
        return res;
    }

    public void updateStatus(){
        for(MRTapeElementPanel tp:elems)tp.setSelected(false);
        if(current<nastro.size()){
            MRTapeElementPanel c = elems.get(current);
            c.setSelected(true);
            jPanel2.scrollRectToVisible(c.getBounds());
        }
        remake_hist();
    }

    public void load(AdattatoreEntrata a){
       byte in=AdattatoreEntrata.EOT;
       nastro.clear();
       elems.clear();
       elemsPanel.removeAll();
       current=0;

       in=a.read();
       while((in&AdattatoreEntrata.EOT)==0){
//           System.err.println("io aggiungo: "+in);
           addelem(in);
           in=a.read();
       }
    }

    public JComponent getHistoricalTapeView(){
        return historicalview;
    }

    public boolean isLoop(){
        return isloop;
    }

    public void setLoop(boolean b){
        isloop=b;
    }
    
    public void save(RegistroUscita u){
        for(Byte v:nastro) //Thank you SUN! Now I can do all this UGLY things..
            if(v!=null)    //..like taking a Byte instance..
                u.write(v);//..and using it as a byte value!! (bleah)
    }
    
  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JButton btnAddFirst;
  private javax.swing.JButton btnAddLast;
  private javax.swing.JButton btnRemove;
  private javax.swing.JPanel elemsPanel;
  private javax.swing.JPanel histcnt2;
  private javax.swing.JPanel histcont;
  private javax.swing.JPanel historicalview;
  private javax.swing.JScrollPane historicalview2;
  private javax.swing.JCheckBox jCheckBox1;
  private javax.swing.JCheckBox jCheckBox6;
  private javax.swing.JLabel jLabel1;
  private javax.swing.JPanel jPanel1;
  private javax.swing.JPanel jPanel2;
  private javax.swing.JPanel jPanel3;
  private javax.swing.JPanel jPanel4;
  private javax.swing.JPanel jPanel5;
  private javax.swing.JScrollPane jScrollPane1;
  private javax.swing.JSeparator jSeparator1;
  private javax.swing.JSeparator jSeparator2;
  // End of variables declaration//GEN-END:variables
    
}
